﻿/*
 * Rappelz: Endless Odyssey - The first free open source Rappelz server emulator
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Rappelz.GameServer.Network;
using System.Data.Common;
using System.Data;
using Rappelz.GameServer.Network.GameClient;

namespace Rappelz.GameServer.Database
{
    /// <summary>
    /// DB_ReadStorageList (smp_insert_favor)
    /// </summary>
    public class DB_ReadStorageList : IDBProc
    {
        private Player m_pPlayer;
        private bool m_bReload;
        public BaseObject m_CBObject = null;

        public DB_ReadStorageList(Player player, bool bReload)
        {
            this.m_pPlayer = player;
            this.m_bReload = bReload;
        }

        public void SetCB(BaseObject obj)
        {
            m_CBObject = obj;
        }

        public void RunCB()
        {
            if (m_CBObject != null)
                m_CBObject.onEndQuery();
        }

        public bool onProcess()
        {
// .text:0051B0EC tmElementalEffectExpire= tm ptr -25Ch
// .text:0051B0EC var_8C          = dword ptr -8Ch
// .text:0051B0EC tElementalEffectExpire= qword ptr -50h
// .text:0051B0EC dtElementalEffectExpire= ATL.COleDateTime ptr -44h
// .text:0051B0EC it              = std._Vector_iterator<StructSummon *,std.allocator<StructSummon *> > ptr  8
// .text:0051B0EC nItemCode       = dword ptr  14h
// .text:0051B0EC nItemUID        = qword ptr  18h
// .text:0051B0EC nCount          = qword ptr  24h
            List<Summon> vSummonList = new List<Summon>();// .text:0051B0EC vSummonList     = std.vector<StructSummon *,std.allocator<StructSummon *> > ptr  2Ch
            List<Pet> vPetList = new List<Pet>();// .text:0051B0EC vPetList        = std.vector<StructPet *,std.allocator<StructPet *> > ptr  3Ch
            int nItemIndex = 0;//      = dword ptr 80 50h
// .text:0051B0EC cmd             = _com_ptr_t<_com_IIID<_Command,&_GUID_b08400bd_f9d1_4d02_b856_71d5dba123e9> > ptr  54h
            bool bIsGoldExist = false;//    = byte ptr  6Fh
// .text:0051B0EC pRS             = _com_ptr_t<_com_IIID<_Recordset,&_GUID_00000556_0000_0010_8000_00aa006d2ea4> > ptr  70h
// .text:0051B0EC db              = dword ptr  7Ch
            int i;

// 
// Data           :   ebp Relative, [0000007C], Param, Type: struct DBConnection &, db
// Data           :   ebp Relative, [0000002C], Local, Type: class std.vector<StructSummon *,std.allocator<StructSummon *> >, vSummonList
// Data           :   ebp Relative, [0000003C], Local, Type: class std.vector<StructPet *,std.allocator<StructPet *> >, vPetList
// Data           :   ebp Relative, [00000050], Local, Type: int, nItemIndex
// Data           :   ebp Relative, [00000054], Local, Type: class _com_ptr_t<_com_IIID<_Command,&_GUID_b08400bd_f9d1_4d02_b856_71d5dba123e9> >, cmd
// Data           :   ebp Relative, [0000006F], Local, Type: bool, bIsGoldExist
// Data           :   ebp Relative, [00000070], Local, Type: class _com_ptr_t<_com_IIID<_Recordset,&_GUID_00000556_0000_0010_8000_00aa006d2ea4> >, pRS
// Data           :   ebp Relative, [00000014], Local, Type: int, nItemCode
// Data           :   ebp Relative, [00000018], Local, Type: __int64, nItemUID
// Data           :   ebp Relative, [FFFFFFB0], Local, Type: __int64, tElementalEffectExpire
// Data           :   ebp Relative, [FFFFFDA4], Local, Type: struct tm, tmElementalEffectExpire
// Data           :   ebp Relative, [00000024], Local, Type: __int64, nCount
// Data           :   ebp Relative, [FFFFFFBC], Local, Type: class ATL.COleDateTime, dtElementalEffectExpire
// Data           :   ebp Relative, [00000008], Local, Type: class std._Vector_iterator<StructSummon *,std.allocator<StructSummon *> >, it
// Data           :   ebp Relative, [00000064], Local, Type: class std._Vector_iterator<StructPet *,std.allocator<StructPet *> >, it
// Data           :   ebp Relative, [00000064], Local, Type: class std._Vector_iterator<StructSummon *,std.allocator<StructSummon *> >, it
// Data           :   ebp Relative, [00000064], Local, Type: class std._Vector_iterator<StructPet *,std.allocator<StructPet *> >, it
// Data           :   ebp Relative, [00000064], Local, Type: class std._Vector_iterator<StructSummon *,std.allocator<StructSummon *> >, it
// Data           :   ebp Relative, [00000064], Local, Type: class std._Vector_iterator<StructPet *,std.allocator<StructPet *> >, it
// 
// 
// 

            DbConnection conn = GameDBManager.Instance.CreateConnection();
            DbCommand cmd = conn.CreateCommand();

            cmd.CommandText = "smp_read_storage_list";
            cmd.CommandType = CommandType.StoredProcedure;

            DbParameter IN_ACCOUNT_ID = GameDBManager.Instance.CreateInParameter(cmd, "IN_ACCOUNT_ID", DbType.Int32, m_pPlayer.GetAccountID());

            conn.Open();
            try
            {
                readStorageSummonList(conn, vSummonList);
                readStoragePetList(conn, vPetList);

                DbDataReaderTypeCastHelper dr = new DbDataReaderTypeCastHelper(cmd.ExecuteReader());
                if(!dr.HasRows)
                {
                    this.m_pPlayer.m_nStorageGoldItemID = Player.allocItemUID();
                    DB_InsertItem.insertItemToDB(this.m_pPlayer.m_nStorageGoldItemID,0,this.m_pPlayer.GetAccountID(),0,0,0,0,0,0,0,
                        0,0,0,0,126,0,0,0,0,0);
                }
                else 
                {
                    while (dr.Read())
                    {
                        int off = 0;
                        long sid = dr.GetInt64(off++);
                        int owner_id = dr.GetInt32(off++);
                        int account_id = dr.GetInt32(off++);
                        int flag = dr.GetInt32(off++);
                        int code = dr.GetInt32(off++);
                        int idx = dr.GetInt32(off++);
                        long cnt = dr.GetInt64(off++);
                        int level = dr.GetInt32(off++);
                        int dura = dr.GetInt32(off++);
                        int enhance = dr.GetInt32(off++);
                        int endurance = dr.GetInt32(off++);
                        ItemInstance.GenerateCode gcode = (ItemInstance.GenerateCode) dr.GetInt32(off++);
                        int wear_info = dr.GetInt32(off++);
                        int socket_0 = dr.GetInt32(off++);
                        int socket_1 = dr.GetInt32(off++);
                        int socket_2 = dr.GetInt32(off++);
                        int socket_3 = dr.GetInt32(off++);
                        int remain_time = dr.GetInt32(off++);
                        Elemental.Type elemental_effect_type = (Elemental.Type) dr.GetByte(off++);
                        DateTime elemental_effect_expire_time = dr.GetDateTime(off++);
                        long elem = (long)(elemental_effect_expire_time - Globals.StartOfEpoch).TotalMilliseconds;
                        int elemental_effect_attack_point = dr.GetInt32(20);
                        int elemental_effect_magic_point = dr.GetInt32(21);

                        if (nItemIndex >= GameRule.nMaxStorageItemCount )
                            break;

                        Item curItem = this.m_pPlayer.m_Storage.FindBySID(sid);
                        if(curItem == null)
                            curItem = this.m_pPlayer.m_Inventory.FindBySID(sid);

                        if (!this.m_bReload || code == 0 || curItem == null)
                        {
                            Item newItem = Item.AllocItem(sid, code, cnt, gcode, level, dura, enhance, flag, socket_0, socket_1, socket_2, socket_3,
                                remain_time, elemental_effect_type, elem, elemental_effect_attack_point, elemental_effect_magic_point);

                            newItem.m_Instance.Flag &= 0xDFFFFFFF;
                            newItem.SetCurrentEndurance(endurance);
                            newItem.SetOwnerInfo(this.m_pPlayer.m_hHandle, 0, this.m_pPlayer.GetAccountID());
                            if (code != 0)
                            {
                                nItemIndex++;

                                newItem.m_Instance.nIdx = nItemIndex;
                                newItem.m_bIsNeedUpdateToDB = true;
                                if (newItem.m_Instance.nIdx == idx)
                                    newItem.m_bIsNeedUpdateToDB = false;

                                Item joinItem = this.m_pPlayer.m_Storage.FindByCode(newItem.m_Instance.Code);
                                if (newItem.IsJoinable() && joinItem != null)
                                {
                                    joinItem.m_Instance.nCount += newItem.m_Instance.nCount;
                                    joinItem.m_bIsNeedUpdateToDB = true;
                                    newItem.SetOwnerInfo(0, 0, 0);
                                    newItem.DBQuery(new DB_UpdateItemOwner(newItem));
                                    Item.PendFreeItem(newItem);
                                    joinItem.DBQuery(new DB_UpdateItem(joinItem));
                                    nItemIndex--;
                                    Messages.SendItemMessage(this.m_pPlayer, joinItem);
                                }
                                else
                                {
                                    if (newItem.m_pItemBase.nGroup == 13)
                                    {
                                        for (i = vSummonList.Count - 1; i >= 0; --i)
                                        {
                                            Summon sm = vSummonList[i];
                                            if (sm.m_nSID == newItem.m_Instance.Socket[0])
                                            {
                                                vSummonList.RemoveAt(i);
                                                sm.m_item = newItem;
                                                newItem.m_pSummon = sm;
                                                newItem.m_Instance.Socket[0] = sm.m_nSID;
                                                newItem.m_bIsNeedUpdateToDB = true;
                                                //readCreatureSkillList(conn, sm);
                                                sm.m_StatusFlag |= Creature.StatusFlags.LoginComplete;
                                                break;
                                            }
                                        }
                                    }
                                    if (newItem.m_pItemBase.nGroup == 18)
                                    {
                                        for (i = vPetList.Count - 1; i >= 0; --i)
                                        {
                                            Pet pet = vPetList[i];
                                            if (pet.m_nSID == newItem.m_Instance.Socket[0])
                                            {
                                                vPetList.RemoveAt(i);
                                                pet.m_item = newItem;
                                                newItem.m_pPet = pet;
                                                newItem.m_Instance.Socket[0] = pet.m_nSID;
                                                newItem.m_bIsNeedUpdateToDB = true;
                                                pet.m_StatusFlag |= Creature.StatusFlags.LoginComplete;


                                                Messages.SendAddPetMessage(this.m_pPlayer, pet);
                                                break;
                                            }
                                        }
                                    }
                                    if (newItem.m_Instance.nIdx == 0)
                                    {
                                        this.m_pPlayer.m_Storage.m_nIndex++;
                                        newItem.m_Instance.nIdx = this.m_pPlayer.m_Storage.m_nIndex;
                                        newItem.m_bIsNeedUpdateToDB = true;
                                    }
                                    this.m_pPlayer.m_Storage.Push(newItem, newItem.m_Instance.nCount, false);
                                }
                            }
                            else if (this.m_bReload)
                            {
                                bIsGoldExist = true;
                                Item.PendFreeItem(newItem);
                            }
                            else
                            {
                                if (this.m_pPlayer.ChangeStorageGold(cnt + this.m_pPlayer.m_nStorageGold) != 0)
                                {
                                    Globals.Log.Error("DB_ReadStorageList.onProcess: Storage gold exceeded the maximum amount.[Account:{0}, ItemSID:{1}, Exist:{2}, Owning:{3}, Loaded:{4}]",
                                        this.m_pPlayer.GetAccountName(), newItem.m_Instance.UID, bIsGoldExist, this.m_pPlayer.m_nStorageGold, cnt);
                                }
                                else
                                {
                                    if (bIsGoldExist)
                                    {
                                        newItem.SetOwnerInfo(0, 0, 0);
                                        newItem.DBQuery(new DB_UpdateItemOwner(newItem));
                                        this.m_pPlayer.DBQuery(new DB_UpdateStorageGold(this.m_pPlayer));
                                    }
                                    else
                                    {
                                        this.m_pPlayer.m_nStorageGoldItemID = newItem.m_Instance.UID;
                                        bIsGoldExist = true;
                                    }
                                }
                                Item.PendFreeItem(newItem);
                            }
                        }
                        else
                        {
                            nItemIndex++;

                            curItem.m_Instance.nIdx = nItemIndex;
                            curItem.m_bIsNeedUpdateToDB = true;

                            if (curItem.m_Instance.nIdx == idx)
                                curItem.m_bIsNeedUpdateToDB = false;
                            Messages.SendItemMessage(this.m_pPlayer, curItem);
                        }
                    }

                    if (!bIsGoldExist)
                    {
                        this.m_pPlayer.m_nStorageGoldItemID = Player.allocItemUID();
                        DB_InsertItem.insertItemToDB(this.m_pPlayer.m_nStorageGoldItemID,0,this.m_pPlayer.GetAccountID(),0,0,0,0,0,0,0,
                            0,0,0,0,126,0,0,0,0,0);
                    }
                }
                this.m_pPlayer.m_bIsStorageLoaded = true;
                ServerLog.Log((ushort)2103, this.m_pPlayer.GetAccountID(), this.m_pPlayer.GetSID(), this.m_pPlayer.GetLevel(), this.m_pPlayer.GetJobLevel(),
                    this.m_pPlayer.GetJobPoint(), this.m_pPlayer.GetJobId(), this.m_pPlayer.m_nGold, this.m_pPlayer.m_nStorageGold, this.m_pPlayer.m_nChaos,
                    (long)this.m_pPlayer.m_fImmoralPoint, this.m_pPlayer.m_nEXP, this.m_pPlayer.GetAccountName(), this.m_pPlayer.GetName(), "", "");
                this.m_pPlayer.OpenStorage();
                this.m_pPlayer.m_bIsStorageRequested = false;

            }
            catch (System.Exception ex)
            {
        	    Globals.Log.Error("Error in DB_ReadStorageList.onProcess: {0}", ex);
            }
            conn.Close();
            return true;

/*
            LODWORD(v300) = *(v2 + 112);
            *(v2 - 4) = 3;
            if ( LODWORD(v300) )
            {
                v301 = *LODWORD(v300);
                v313 = v300;
                (*(v301 + 8))(LODWORD(v300));
            }
            LODWORD(v302) = *(v2 + 84);
            *(v2 - 4) = 2;
            if ( LODWORD(v302) )
            {
                v303 = *LODWORD(v302);
                v313 = v302;
                (*(v303 + 8))(LODWORD(v302));
            }
            v69 = *(v2 + 48) == 0;
            *(v2 - 4) = 1;
            if ( !v69 )
            {
                if ( (*(v2 + 52) - *(v2 + 48)) >> 2 )
                {
                    LODWORD(v313) = v2 + 44;
                    v312 = *(v2 + 48);
                    std._Vector_const_iterator<StateDamage_std.allocator<StateDamage>>._Vector_const_iterator<StateDamage_std.allocator<StateDamage>>(
                        (v2 + 100),
                        v312,
                        (v2 + 44));
                    while ( 1 )
                    {
                        LODWORD(v313) = v2 + 44;
                        v312 = *(v2 + 52);
                        std._Vector_const_iterator<StateDamage_std.allocator<StateDamage>>._Vector_const_iterator<StateDamage_std.allocator<StateDamage>>(
                            (v2 + 88),
                            v312,
                            (v2 + 44));
                        if ( std._Vector_const_iterator<X2D.Point<float>_std.allocator<X2D.Point<float>>>.operator__(
                                 (v2 + 100),
                                 (v2 + 88)) )
                            break;
                        v313 = std._Vector_const_iterator<PartyManager.PartyInfo___std.allocator<PartyManager.PartyInfo__>>.operator_((v2 + 100)).end.x;
                        v304 = ArcadiaServer.Instance();
                        ArcadiaServer.DeleteObject(v304, LODWORD(v313));
                        std._Vector_const_iterator<AutoAuctionInfo___std.allocator<AutoAuctionInfo__>>.operator__((v2 + 100));
                    }
                }
            }
            if ( *(v2 + 64) )
            {
                if ( (*(v2 + 68) - *(v2 + 64)) >> 2 )
                {
                    LODWORD(v313) = v2 + 60;
                    v312 = *(v2 + 64);
                    std._Vector_const_iterator<StateDamage_std.allocator<StateDamage>>._Vector_const_iterator<StateDamage_std.allocator<StateDamage>>(
                        (v2 + 100),
                        v312,
                        (v2 + 60));
                    while ( 1 )
                    {
                        LODWORD(v313) = v2 + 60;
                        v312 = *(v2 + 68);
                        std._Vector_const_iterator<StateDamage_std.allocator<StateDamage>>._Vector_const_iterator<StateDamage_std.allocator<StateDamage>>(
                            (v2 + 88),
                            v312,
                            (v2 + 60));
                        if ( std._Vector_const_iterator<X2D.Point<float>_std.allocator<X2D.Point<float>>>.operator__(
                                 (v2 + 100),
                                 (v2 + 88)) )
                            break;
                        v313 = std._Vector_const_iterator<PartyManager.PartyInfo___std.allocator<PartyManager.PartyInfo__>>.operator_((v2 + 100)).end.x;
                        v305 = ArcadiaServer.Instance();
                        ArcadiaServer.DeleteObject(v305, LODWORD(v313));
                        std._Vector_const_iterator<AutoAuctionInfo___std.allocator<AutoAuctionInfo__>>.operator__((v2 + 100));
                    }
                }
            }
*/
            return true;
        }

        bool readStoragePetList(DbConnection conn, List<Pet> vPetList)
        {
            return true;
        }

        bool readStorageSummonList(DbConnection conn, List<Summon> vSummonList)
        {
            return true;
        }


    }
}

